/*******************************************************************************
 * Copyright (c) 2012 Alexandr Tsvetkov.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Alexandr Tsvetkov - initial API and implementation
 * 
 * Project:
 *     TAO Library
 * 
 * File name:
 *     BitmapManager.java
 *     
 * License agreement:
 *
 * 1. This code is published AS IS. Author is not responsible for any damage that can be
 *    caused by any application that uses this code.
 * 2. Author does not give a garantee, that this code is error free.
 * 3. This code can be used in NON-COMMERCIAL applications AS IS without any special
 *    permission from author.
 * 4. This code can be modified without any special permission from author IF AND ONLY IF
 *    this license agreement will remain unchanged.
 * 5. SPECIAL PERMISSION for this code usage in COMMERCIAL application SHOULD be obtained
 *    from author.
 ******************************************************************************/
package ua.at.tsvetkov.images;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import ua.at.tsvetkov.file.IO;
import ua.at.tsvetkov.util.Log;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.media.ThumbnailUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;

/**
 * Класс для работы с изображениями в формате Bitmap
 * 
 * @author A.Tsvetkov 2010 http://tsvetkov.at.ua mailto:al@ukr.net
 */
public class BitmapManager {

	/**
	 * Загрузка изображения по url в Bitmap. При ошибке загрузки возвращает null.
	 * 
	 * @param stURL адрес загрузки
	 * @return
	 */
	@Deprecated
	public static Bitmap getBitmap(String urlStr, String tmpPath) {
		if (urlStr == null || urlStr.length() == 0) {
			Log.w("Wrong image url " + urlStr);
			return null;
		}
		IO.downloadFile(urlStr, tmpPath);
		Bitmap bm = BitmapFactory.decodeFile(tmpPath);
		if (bm == null) {
			Log.e("Image data could not be decoded! " + urlStr);
		} else {
			Log.v("Image loaded success " + urlStr);
		}
		return bm;
	}

	/**
	 * Загрузка изображения с предварительным кешированием в указанном месте. Возвращает Bitmap. При ошибке загрузки возвращает null.
	 * 
	 * @param urlStr адрес загрузки
	 * @param сacheFile путь к кешированному файлу
	 * @return Bitmap
	 */
	public static Bitmap getCachedBitmap(String urlStr, String сacheFile) {
		Bitmap result = null;
		try {
			if (!new File(сacheFile).exists() && !IO.downloadFile(urlStr, сacheFile))
				return null;
			result = BitmapFactory.decodeFile(сacheFile);
		} catch (Exception e) {
			Log.e("Can't load file " + сacheFile + " from " + urlStr, e);
			return null;
		}
		return result;
	}

	/**
	 * Загрузка изображения с предварительным кешированием в указанном месте. Возвращает Bitmap. При ошибке загрузки возвращает null.
	 * 
	 * @param urlStr адрес загрузки
	 * @return Bitmap
	 */
	public static Bitmap getCachedBitmapResized(String urlStr, String newCachFile, int width, int height) {
		Bitmap result = null;
		try {
			if (!new File(newCachFile).exists() && !IO.downloadFile(urlStr, newCachFile))
				return null;
			result = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(newCachFile), width, height);
		} catch (Exception e) {
			Log.e("Can't load file " + newCachFile + " from " + urlStr, e);
			return null;
		}
		return result;
	}

	/**
	 * Загрузка изображения с обязательной перезаписью в указанном месте. Возвращает Bitmap. При ошибке загрузки возвращает null.
	 * 
	 * @param urlStr адрес загрузки
	 * @return Bitmap
	 */
	public static Bitmap getBitmapResized(String urlStr, String tmpFile, int width, int height) {
		Bitmap result = null;
		try {
			if (!IO.downloadFile(urlStr, tmpFile))
				return null;
			result = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(tmpFile), width, height);
		} catch (Exception e) {
			Log.e("Can't load file " + tmpFile + " from " + urlStr, e);
			return null;
		}
		return result;
	}

	/**
	 * Загружает файл изображения и изменяет размер Bitmap. Размер должен быть кратен 2.
	 * 
	 * @param fileName путь к файлу
	 * @param size нужный размер
	 * @return
	 */
	public static Bitmap getResizedBitmap(String fileName, int size) {
		try {
			BitmapFactory.Options factoryOptions = new BitmapFactory.Options();
			factoryOptions.inJustDecodeBounds = true;
			BitmapFactory.decodeStream(new FileInputStream(fileName), null, factoryOptions);
			int width_tmp = factoryOptions.outWidth, heightTmp = factoryOptions.outHeight;
			int scale = 1;
			while (true) {
				if (width_tmp / 2 < size || heightTmp / 2 < size)
					break;
				width_tmp /= 2;
				heightTmp /= 2;
				scale++;
			}
			// Decode with inSampleSize
			factoryOptions = new BitmapFactory.Options();
			factoryOptions.inSampleSize = scale;
			return BitmapFactory.decodeStream(new FileInputStream(fileName), null, factoryOptions);
		} catch (Exception e) {
			Log.e("getResizedBitmap", e);
			return null;
		}
	}

	/**
	 * Загружает файл изображения из Интернет, кеширует на карте и возвращает Bitmap с измененными размерами для создания превью например. Размер должен быть кратен 2.
	 * 
	 * @param urlStr адрес файла в интернет
	 * @param size нужные размер
	 * @param newCachFile путь к кэшируемому файлу
	 * @return
	 */
	public static Bitmap getCachedResizedBitmapFromUrl(String urlStr, int size, String newCachFile) {

		try {
			File tmp = new File(newCachFile);
			if (!tmp.exists() || tmp.length() == 0) {
				Log.i("Cover not exist");
				if (IO.downloadFile(urlStr, newCachFile)) {
					Log.i("Cover Downloaded");
					return getResizedBitmap(newCachFile, size);
				}
			} else {
				Log.i("Cover exist");
				return BitmapFactory.decodeFile(newCachFile);
			}
		} catch (Exception e) {
			Log.e("decodeFile");
		}
		return null;
	}

	/**
	 * Загружает файл изображения c sdcard, и возвращает Bitmap с измененными размерами для создания превью например. Размер должен быть кратен 2.
	 * 
	 * @param fName имя файла на карте
	 * @param size нужные размер
	 * @param newCachFile путь к кэшируемому файлу
	 * @return
	 */
	public static Bitmap getCachedResizedBitmap(String fName, int size, String newCacheFile) {
		try {
			if (!new File(newCacheFile).exists()) {
				Bitmap bitmap = getResizedBitmap(fName, size);
				FileOutputStream out = new FileOutputStream(newCacheFile);
				bitmap.compress(Bitmap.CompressFormat.PNG, 70, out);
				return bitmap;
			} else {
				return BitmapFactory.decodeFile(fName);
			}
		} catch (Exception e) {
			Log.e("decodeFile");
		}
		return null;
	}

	/**
	 * Загружает Bitmap из ассетсов.
	 * 
	 * @param context
	 * @param name
	 * @return Bitmap
	 * @throws IOException
	 */
	public static Bitmap loadBitmapFromAssets(Context context, String name) throws IOException {
		InputStream is = null;
		Bitmap res = null;
		is = context.getAssets().open(name);
		res = BitmapFactory.decodeStream(is);
		is.close();
		return res;
	}

	/**
	 * Generate bitmap from layout.
	 * @param context
	 * @param id
	 * @return
	 */
	public static Bitmap getBitmapFromLayout(Context context, int id) {
		View view = LayoutInflater.from(context).inflate(id, null);
		return getBitmapFromView(view);
	}

	/**
	 * Generate bitmap from view.
	 * @param view
	 * @return
	 */
	public static Bitmap getBitmapFromView(View view) {
		if (view.getMeasuredHeight() <= 0) {
			view.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
			Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
			Canvas canvas = new Canvas(bitmap);
			view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
			view.draw(canvas);
			return bitmap;
		} else {
			Bitmap bitmap = Bitmap.createBitmap(view.getLayoutParams().width, view.getLayoutParams().height, Bitmap.Config.ARGB_8888);
			Canvas canvas = new Canvas(bitmap);
			view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
			view.draw(canvas);
			return bitmap;

		}
	}

}
